package io.esirong.image;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.drawable.Drawable;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Android Bitmap工具类，提供对Bitmap处理的常用方法
 * <P></P>
 * 缩放（拉伸）
 * 旋转
 */
public class BitmapUtils {
    /**
     * 根据给定的宽和高进行拉伸
     *
     * @param origin 原图
     * @param newW   新图的宽
     * @param newH   新图的高
     * @return new Bitmap
     */
    public static Bitmap scaleBitmap(Bitmap origin, int newW, int newH) {
        if (origin == null) {
            return null;
        }
        int srcH = origin.getHeight();
        int srcW = origin.getWidth();
        float scaleWidth = ((float) newW) / srcW;
        float scaleHeight = ((float) newH) / srcH;
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);// 使用后乘
        Bitmap newBmp = Bitmap.createBitmap(origin, 0, 0, srcW, srcH, matrix, false);
        if (!origin.isRecycled()) {
            origin.recycle();
        }
        return newBmp;
    }

    /**
     * 按比例缩放图片
     *
     * @param origin 原图
     * @param ratio  比例
     * @return 新的bitmap
     */
    public static Bitmap scaleBitmap(Bitmap origin, float ratio) {
        if (origin == null) {
            return null;
        }
        int srcW = origin.getWidth();
        int srcH = origin.getHeight();
        Matrix matrix = new Matrix();
        matrix.preScale(ratio, ratio);
        Bitmap newBmp = Bitmap.createBitmap(origin, 0, 0, srcW, srcH, matrix, false);
        if (newBmp.equals(origin)) {
            return newBmp;
        }
        origin.recycle();
        return newBmp;
    }

    /**
     * 裁剪
     *
     * @param origin 原图
     * @return 裁剪后的图像
     */
    public static Bitmap cropBitmap(Bitmap origin) {
        int srcW = origin.getWidth(); // 得到图片的宽，高
        int srcH = origin.getHeight();
        int cropWidth = srcW >= srcH ? srcH : srcW;// 裁切后所取的正方形区域边长
        cropWidth /= 2;
        int cropHeight = (int) (cropWidth / 1.2);
        return Bitmap.createBitmap(origin, srcW / 3, 0, cropWidth, cropHeight, null, false);
    }

    /**
     * 裁剪
     *
     * @param origin 原图
     * @return 裁剪后的图像
     */
    public static Bitmap cropBitmap(Bitmap origin, int srcX, int srcY, int newW, int newH) {
        return Bitmap.createBitmap(origin, srcX, srcY, newW, newH, null, false);
    }

    /**
     * 裁剪
     *
     * @param origin 原图
     * @return 裁剪后的图像
     */
    public static Bitmap cropCenterBitmap(Bitmap origin, int newW, int newH) {
        int srcW = origin.getWidth(); // 得到图片的宽，高
        int srcH = origin.getHeight();
        if (newW > srcW || newH > srcH) {
            return null;
        }
        int srcX = (srcW - newW) / 2;
        int srcY = (srcH - newH) / 2;
        return Bitmap.createBitmap(origin, srcX, srcY, newW, newH, null, false);
    }

    /**
     * 选择变换
     *
     * @param origin 原图
     * @param angle  旋转角度，可正可负
     * @return 旋转后的图片
     */
    public static Bitmap rotateBitmap(Bitmap origin, float angle) {
        if (origin == null) {
            return null;
        }
        int srcW = origin.getWidth();
        int srcH = origin.getHeight();
        Matrix matrix = new Matrix();
        matrix.setRotate(angle);
        // 围绕原地进行旋转
        Bitmap newBmp = Bitmap.createBitmap(origin, 0, 0, srcW, srcH, matrix, false);
        if (newBmp.equals(origin)) {
            return newBmp;
        }
        origin.recycle();
        return newBmp;
    }

    /**
     * 偏移效果
     *
     * @param origin 原图
     * @return 偏移后的bitmap
     */
    public static Bitmap skewBitmap(Bitmap origin) {
        if (origin == null) {
            return null;
        }
        int srcW = origin.getWidth();
        int srcH = origin.getHeight();
        Matrix matrix = new Matrix();
        matrix.postSkew(-0.6f, -0.3f);
        Bitmap newBmp = Bitmap.createBitmap(origin, 0, 0, srcW, srcH, matrix, false);
        if (newBmp.equals(origin)) {
            return newBmp;
        }
        origin.recycle();
        return newBmp;
    }

    /**
     * 居中裁剪图片
     *
     * @param origin 源图
     * @return 裁剪图
     */
    public static Bitmap circleBitmapCenter(Bitmap origin) {
        int srcW = origin.getWidth();
        int srcH = origin.getHeight();
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        Bitmap newBmp = Bitmap.createBitmap(srcW, srcH, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(newBmp);
        int radius = Math.min(srcW / 2, srcH / 2);
        canvas.drawCircle(srcW >> 1, srcH >> 1, radius, paint);
        //设置画笔为取交集模式
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        //裁剪图片
        int left = 0;
        int top = 0;
        canvas.drawBitmap(origin, left, top, paint);
        return newBmp;
    }

    /**
     * 压缩图片大小（容量压缩法）
     * <p>尝试将图片压缩到指定容量。注意，这可能无法保证图像的显示质量。
     *
     * @param bitmap 源图
     * @param size   限定大小.单位【KB】
     * @return 压缩后的图片
     */
    public static Bitmap compressImage(Bitmap bitmap, long size) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
        int options = 100;
        while (baos.toByteArray().length / 1024 > size) { // 循环判断如果压缩后图片是否大于size KB,大于继续压缩
            baos.reset();// 重置baos即清空baos
            bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%，把压缩后的数据存放到baos中
            options -= 10;// 每次都减少10
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
        // 把ByteArrayInputStream数据生成图片
        return BitmapFactory.decodeStream(isBm, null, null);
    }

    /**
     * 压缩图片大小
     *
     * @param image 源图
     * @return 压缩后的图片
     */
    public static Bitmap compressImage(Bitmap image) {
        int size = 100;//100k
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
        int options = 100;
        while (baos.toByteArray().length / 1024 > size) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
            baos.reset();// 重置baos即清空baos
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%，把压缩后的数据存放到baos中
            options -= 10;// 每次都减少10
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
        // 把ByteArrayInputStream数据生成图片
        return BitmapFactory.decodeStream(isBm, null, null);
    }

    /**
     * 将彩色图转换为灰度图
     *
     * @param img 待处理的图像
     * @return 压缩后的图片
     */
    public static Bitmap convertGreyImg(Bitmap img) {
        int width = img.getWidth(); // 获取位图的宽
        int height = img.getHeight(); // 获取位图的高

        int[] pixels = new int[width * height]; // 通过位图的大小创建像素点数组

        img.getPixels(pixels, 0, width, 0, 0, width, height);
        int alpha = 0xFF << 24;
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                int grey = pixels[width * i + j];

                int red = ((grey & 0x00FF0000) >> 16);
                int green = ((grey & 0x0000FF00) >> 8);
                int blue = (grey & 0x000000FF);

                grey = (int) ((float) red * 0.3 + (float) green * 0.59 + (float) blue * 0.11);
                grey = alpha | (grey << 16) | (grey << 8) | grey;
                pixels[width * i + j] = grey;
            }
        }
        Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        result.setPixels(pixels, 0, width, 0, 0, width, height);
        return result;
    }


    /**
     * 生成水印图片 水印在右下角
     *
     * @param src       源图
     * @param watermark 水印图
     * @return 压缩后的图片
     */
    public static Bitmap createWatermarkBitmap(Bitmap src, Bitmap watermark) {
        if (src == null) {
            return null;
        }

        int w = src.getWidth();
        int h = src.getHeight();
        int ww = watermark.getWidth();
        int wh = watermark.getHeight();
        // create the new blank bitmap
        Bitmap newb = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);// 创建一个新的和SRC长度宽度一样的位图
        Canvas cv = new Canvas(newb);
        cv.drawBitmap(src, 0, 0, null);// 在 0，0坐标开始画入src
        cv.drawBitmap(watermark, w - ww + 5, h - wh + 5, null);// 在src的右下角画入水印
        cv.save();  // 保存
        cv.restore();// 存储
        return newb;
    }


    /**
     * 将Drawable转化成Bitmap
     *
     * @param drawable 待转换的Drawable
     * @return Bitmap {@link Bitmap}
     */
    public static Bitmap drawableToBitmap(Drawable drawable) {
        Bitmap bitmap = Bitmap.createBitmap(
                drawable.getIntrinsicWidth(),
                drawable.getIntrinsicHeight(),
                drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        drawable.draw(canvas);
        return bitmap;
    }

    /**
     * 保存图片到文件
     */
    public static void saveBitmapToFile(Bitmap bitmap, String path) {
        File file = new File(path);
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(file);
            if (bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out)) {
                out.flush();
                out.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 根据路径获得图片信息并按比例压缩，返回bitmap
     *
     * @param filePath 图片路径
     * @return 图片（480*800）
     */
    public static Bitmap getSmallBitmap(String filePath) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;//只解析图片边沿，获取宽高
        BitmapFactory.decodeFile(filePath, options);
        // 计算缩放比
        options.inSampleSize = calculateInSampleSize(options, 480, 800);
        // 完整解析图片返回bitmap
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(filePath, options);
    }

    /**
     * 计算需要的装载的内存大小
     *
     * @param options   配置信息
     * @param reqWidth  需要图宽
     * @param reqHeight 需要图高
     * @return 内存大小
     */
    public static int calculateInSampleSize(BitmapFactory.Options options,
                                            int reqWidth, int reqHeight) {
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            final int heightRatio = Math.round((float) height / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        return inSampleSize;
    }

}
